package moltencore.config;

import org.apache.log4j.Logger;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import moltencore.config.exception.ConfigReaderException;

public class ConfigReader {
	private static Logger logger = Logger.getLogger(ConfigReader.class);

	private static final String PROPERTY_QUERY_UDP_PORT = "queryUdpPort";
	private static final String PROPERTY_RESPONSE_UDP_PORT = "responseUdpPort";
	private static final String PROPERTY_CANNON_ROTATION_UPDATE_FREQUENCY_SECONDS = "cannonRotationUpdateFrequencySeconds";
	private static final String PROPERTY_CANNON_PANNING_SPEED = "cannonPanningSpeed";
	private static final String PROPERTY_CANNON_FIRE_FORCE = "cannonFireForce";
	private static final String PROPERTY_ORDINARY_BUBBLE_PROBABILITY = "ordinaryBubbleProbability";
	private static final String PROPERTY_GHOST_BUBBLE_PROBABILITY = "ghostBubbleProbability";
	private static final String PROPERTY_RAINBOW_BUBBLE_PROBABILITY = "rainbowBubbleProbability";
	private static final String PROPERTY_BLAZING_BUBBLE_PROBABILITY = "blazingBubbleProbability";
	private static final String PROPERTY_FRAME_BREAK = "frameBreak";
	private static final String PROPERTY_PUSH_COUNT = "pushCount";
	private static final String PROPERTY_RESOURCE_PATH = "resourcePath";

	public void initializeConfig(String configFilePath) throws ConfigReaderException {
		//create an input stream from the specified location of the config file
		FileInputStream fileInputStream;
		try {
			fileInputStream = new FileInputStream(configFilePath);
		}
		catch(FileNotFoundException e) {
			throw new ConfigReaderException(e);
		}

		//craete properties on the config file stream
		Properties properties = new Properties();
		try {
			properties.load(fileInputStream);
		}
		catch(IOException e) {
			throw new ConfigReaderException(e);
		}

		//load config values
		Config.getInstance().setQueryUdpPort(readInteger(properties, PROPERTY_QUERY_UDP_PORT));
		Config.getInstance().setResponseUdpPort(readInteger(properties, PROPERTY_RESPONSE_UDP_PORT));
		Config.getInstance().setCannonRotationUpdateFrequencySeconds(readFloat(properties, PROPERTY_CANNON_ROTATION_UPDATE_FREQUENCY_SECONDS));
		Config.getInstance().setCannonFireForce(readFloat(properties, PROPERTY_CANNON_FIRE_FORCE));
		Config.getInstance().setCannonPanningSpeed(readFloat(properties, PROPERTY_CANNON_PANNING_SPEED));
		Config.getInstance().setOrdinaryBubbleProbability(readFloat(properties, PROPERTY_ORDINARY_BUBBLE_PROBABILITY));
		Config.getInstance().setGhostBubbleProbability(readFloat(properties, PROPERTY_GHOST_BUBBLE_PROBABILITY));
		Config.getInstance().setRainbowBubbleProbability(readFloat(properties, PROPERTY_RAINBOW_BUBBLE_PROBABILITY));
		Config.getInstance().setBlazingBubbleProbability(readFloat(properties, PROPERTY_BLAZING_BUBBLE_PROBABILITY));
		Config.getInstance().setFrameBreak(readInteger(properties, PROPERTY_FRAME_BREAK));
		Config.getInstance().setPushCount(readInteger(properties, PROPERTY_PUSH_COUNT));
		Config.getInstance().setResourcePath(readString(properties, PROPERTY_RESOURCE_PATH));
	}

	private Integer readInteger(Properties properties, String property) throws ConfigReaderException {
		String integer = properties.getProperty(property);

		if(integer != null) {
			try{
				return Integer.parseInt(integer);
			}
			catch(NumberFormatException e) {
				throw new ConfigReaderException("Invaild value on " + property + ": " + integer);
			}
		}
		else {
			return null;
		}
	}

	private String readString(Properties properties, String property) throws ConfigReaderException {
		String string = properties.getProperty(property);

		if(string == null) {
			throw new ConfigReaderException("Invaild value on " + property + ": " + string);
		}
		else {
			return string;
		}
	}

	private Float readFloat(Properties properties, String property) throws ConfigReaderException {
		String floatValue = properties.getProperty(property);

		if(floatValue != null) {
			try{
				return Float.parseFloat(floatValue);
			}
			catch(NumberFormatException e) {
				throw new ConfigReaderException("Invaild value on " + property + ": " + floatValue);
			}
		}
		else {
			return null;
		}
	}
}
